package com.logos.cartoon.service.impl;

import com.alibaba.fastjson.JSON;
import com.logos.cartoon.constant.CharacterConstant;
import com.logos.cartoon.converter.CharacterInfoConverter;
import com.logos.cartoon.entity.CharacterInfo;
import com.logos.cartoon.enums.AiModelEnum;
import com.logos.cartoon.handler.AiModelHandler;
import com.logos.cartoon.handler.AiModelHandlerFactory;
import com.logos.cartoon.mapper.CharacterInfoMapper;
import com.logos.cartoon.mapper.CharacterLikedMapper;
import com.logos.cartoon.redis.RedisUtil;
import com.logos.cartoon.req.ChatReq;
import com.logos.cartoon.resp.CharacterInfoResp;
import com.logos.cartoon.service.CharacterInfoService;
import com.logos.cartoon.utils.LoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 角色信息表(CharacterInfo)表服务实现类
 *
 * @author rose
 * @since 2025-03-18 14:55:23
 */
@Service("characterInfoService")
@Slf4j
public class CharacterInfoServiceImpl implements CharacterInfoService {
    @Resource
    private CharacterInfoMapper characterInfoMapper;

    @Resource
    private CharacterLikedMapper characterLikedMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private LoginUtil loginUtil;

    @Resource
    private AiModelHandlerFactory aiModelHandlerFactory;

    public static final String CHARACTER_INFO_LIST = "character:info:list";

    private static final String CHAR_LIKED_COUNT_KEY = "character:liked:count";

    private static final String CHAR_LIKED_DETAIL_KEY = "character:liked:detail";

    public static final String RANK_KEY = "character:rank";

    public static final String DAY_CHARACTER_KEY = "character:day:";

    public static final String RANK_HOT = "character:rank:hot";

    public static final String aiUrl = "http://localhost:11434/api/chat";



    @Override
    public CharacterInfoResp queryById(Long id) {
        // 查询当前角色信息
        CharacterInfo characterInfo = characterInfoMapper.queryById(id);
        if (characterInfo == null) {
            return null;
        }
        CharacterInfoResp characterInfoResp = CharacterInfoConverter.INSTANCE.convertEntityToResp(characterInfo);
        // 查询给当前角色点赞的用户个数
//        characterLikedMapper.queryCount(id);
        // TODO 先在redis中查，后期实现mq消息发送，将redis数据写入数据库中再在数据库中查
        Integer likeCount = redisUtil.getInt(CHAR_LIKED_COUNT_KEY + ":" + id);
        likeCount = Objects.isNull(likeCount) ? 0 : likeCount;
        // 查询当前用户是否给当前角色点过赞
        if (redisUtil.exist(CHAR_LIKED_DETAIL_KEY + ":" + id + ":" + loginUtil.getId())) {
            characterInfoResp.setStatus(1);
        } else {
            characterInfoResp.setStatus(0);
        }
        characterInfoResp.setLikeCount(likeCount);
        // 查询收藏了当前角色的用户个数
        // TODO 收藏代办
        characterInfoResp.setCollectCount(10);
        return characterInfoResp;
    }

    /**
     * 新增数据
     *
     * @param characterInfo 实例对象
     * @return 实例对象
     */
    @Override
    public CharacterInfo insert(CharacterInfo characterInfo) {
        this.characterInfoMapper.insert(characterInfo);
        return characterInfo;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.characterInfoMapper.deleteById(id) > 0;
    }

    @Override
    public List<CharacterInfo> queryAll() {
        // 查看是否存在缓存，存在则直接返回缓存
        if (redisUtil.exist(CHARACTER_INFO_LIST)) {
            log.info("character.info.list cache hit");
            String data = redisUtil.get(CHARACTER_INFO_LIST);
            log.debug("Cached data: {}", data); // 添加日志记录以检查数据格式
            List<CharacterInfo> result = JSON.parseArray(data, CharacterInfo.class);
            return result;
        }
        // 查询数据库
        List<CharacterInfo> result = characterInfoMapper.selectByLimit(CharacterConstant.ALL_LIMIT);
        // 缓存数据,有效期三分钟
        redisUtil.setNx(CHARACTER_INFO_LIST, JSON.toJSONString(result), 3L, TimeUnit.MINUTES);
        return result;
    }

    @Override
    public List<CharacterInfoResp> hotRank() {
        // 先去查询缓存
        if (redisUtil.exist(RANK_HOT)) {
            log.info("hotRank.cache hit");
            String data = redisUtil.get(RANK_HOT);
            List<CharacterInfoResp> result = JSON.parseArray(data, CharacterInfoResp.class);
            return result;
        }
        Set<ZSetOperations.TypedTuple<String>> typedTuples = redisUtil.rankWithScore(RANK_KEY, 0, 2);
        if (log.isInfoEnabled()) {
            log.info("hotRank.typeTuples:{}", JSON.toJSONString(typedTuples));
        }
        if (CollectionUtils.isEmpty(typedTuples)) {
            return Collections.emptyList();
        }
        List<CharacterInfoResp> data = new ArrayList<>();
        typedTuples.forEach(rank -> {
//            String characterIdStr = String.valueOf(rank.getValue());
            Long characterId = Long.parseLong(String.valueOf(rank.getValue()));
            CharacterInfo characterInfo = characterInfoMapper.queryById(characterId);
            CharacterInfoResp characterInfoResp = CharacterInfoConverter.INSTANCE.convertEntityToResp(characterInfo);
            characterInfoResp.setLikeCount(rank.getScore().intValue());
            data.add(characterInfoResp);
        });
        // 根据点赞量排序
        data.sort((o1, o2) -> o2.getLikeCount() - o1.getLikeCount());
        // 缓存数据,有效期30s
        redisUtil.setNx(RANK_HOT, JSON.toJSONString(data), 30L, TimeUnit.SECONDS);
        return data;
    }

    @Override
    public List<CharacterInfoResp> search(String keyword) {
        log.info("CharacterInfoServiceImpl.search.keyword:{}", keyword);
        CharacterInfo characterInfo = new CharacterInfo();
        characterInfo.setCharacterName(keyword);
        List<CharacterInfoResp> characterInfoRespList = characterInfoMapper.queryByCondition(characterInfo, CharacterConstant.ALL_LIMIT);
        executeLike(characterInfoRespList);
        return characterInfoRespList;
    }

    private void executeLike(List<CharacterInfoResp> characterInfoRespList) {
        characterInfoRespList.forEach(characterInfoResp -> {
            // 查询点赞数
            Integer likeCount = redisUtil.getInt(CHAR_LIKED_COUNT_KEY + ":" + characterInfoResp.getId());
            likeCount = Objects.isNull(likeCount) ? 0 : likeCount;
            // 查询当前用户是否给该角色点过赞
            if (redisUtil.exist(CHAR_LIKED_DETAIL_KEY + ":" + characterInfoResp.getId() + ":" + loginUtil.getId())) {
                characterInfoResp.setStatus(1);
            } else {
                characterInfoResp.setStatus(0);
            }
            characterInfoResp.setLikeCount(likeCount);
        });
    }

    @Override
    public CharacterInfoResp random() {
        // 直接去redis中查
        String dataStr = redisUtil.get(DAY_CHARACTER_KEY + new Date().getDate());
        if (StringUtils.isNotBlank(dataStr)) {
            log.info("CharacterInfoServiceImpl.random.cache hit");
            CharacterInfoResp characterInfoResp = JSON.parseObject(dataStr, CharacterInfoResp.class);
            // 设置点赞状态
            if (redisUtil.exist(CHAR_LIKED_DETAIL_KEY + ":" + characterInfoResp.getId() + ":" + loginUtil.getId())) {
                // 1为当前用户已经对该角色点赞
                characterInfoResp.setStatus(1);
            } else {
                // 0 表示当前用户没有对该角色点赞
                characterInfoResp.setStatus(0);
            }
            return characterInfoResp;
        } else {
            log.info("CharacterInfoServiceImpl.random.cache miss");
        }
        return null;
    }

    @Override
    public List<CharacterInfoResp> chatList() {
        // 查询所有角色中is_chat = 1 and is_delete = 0的角色
        CharacterInfo characterInfo = new CharacterInfo();
        characterInfo.setIsChat(1);
        characterInfo.setIsDeleted(0);
        List<CharacterInfoResp> characterInfoRespList = characterInfoMapper.queryByCondition(characterInfo, CharacterConstant.ALL_LIMIT);
        executeLike(characterInfoRespList);
        return characterInfoRespList;
    }

    @Override
    public String chat(ChatReq chatReq) {
        // 工厂+策略模式
        AiModelHandler handler = aiModelHandlerFactory.getHandler(chatReq.getCharacterId());
        String ret = handler.chat(chatReq);
        return ret;
    }

}